-
-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: redefine the trait inheritance behavior #532
fix: redefine the trait inheritance behavior #532
Conversation
08d6644
to
1874ac7
Compare
Now it aims to be identical to JSON Merge patch
1874ac7
to
06db043
Compare
Added some further clarifications to avoid target object naming confusion
Kudos, SonarCloud Quality Gate passed! |
|
||
When traits ([Operation Trait Object](#operationTraitObject) and [Message Trait Object](#messageTraitObject)) are defined, they MUST be merged into the target object according to the following rules: | ||
|
||
* Traits are merged with a recursive merge algorithm, as defined in the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) RFC. To summarize the main merge rules as a merge from source object into a target object: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused now. If this is as defined in JSON Merge Patch, why do we have custom rules below? I'm also having a hard time figuring out how this would work. Maybe we could have some examples along with the explanation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm also unsure about that.
So the RFC already states the merge rules, but it also covers many other aspects that are not relevant to this trait inheritance at all. If you get the rules right, you could just state a few rules here. I still thinks its valuable to say that this is RFC-7386 conformant, so you can reuse existing libraries.
In the linked issue, I've referenced some examples and code. I wasn't sure if this should be part of the specification itself? But having some examples and code is always helful if you can link to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fmvilas Btw. some of those rules are still necessary because they are not part of the JSON Merge Patch RFC.
The following rules are specific to AsyncAPI itself and have been missing (undefined) previously:
- Before applying merges, JSON Schema
$ref
MUST be dereferenced - The Message Object and the Operation Object that the trait is applied to is the most specific and is therefore never overwritten, only extended.
The following rule is AsyncAPI specific but was already there before I think:
- The order of the traits defines their specificity. Subsequent traits in the trait array are more specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should just explicitly state the extension to the RFC? 🤔 That way we ensure there is less interpretation involved.
Something similar to:
The traits ([Operation Trait Object](#operationTraitObject) and [Message Trait Object](#messageTraitObject)) are defined using [JSON Merge Patch](https://tools.ietf.org/html/rfc7386). In extension to these merge rules, the following applies:
- Any references in traits, must be resolved before applying them.
- The Message Object and the Operation Object that the trait is applied to is the most specific and is therefore never overwritten, only extended.
- The order of the traits defines their specificity. Subsequent traits in the trait array are more specific.
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For your coding examples, do you mind writing a comment in this issue: asyncapi/parser-api#36
This way we can include your examples as documentation and explanation of how to achieve the correct behavior in tooling 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Jonas,
sure, I can do that! However, we were not completely agreeing on what the future approach should be.
This code example was my take on how I would do it ;)
Best,
Simon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh yea, my bad, I saw this PR as an attempt to clarify the current behavior. Gonna follow up in #557
Don't worry about versioning in the PR. We handle the release process separately.
I think we should. Inventing new algorithms will make it harder for tooling implementers. I agree that maybe we can reverse the order in which the merge is applied though. My two cents. Would love to know what others think. |
This pull request has been automatically marked as stale because it has not had recent activity 😴 |
Proposal shared with the wider community:
|
I am intrigued by the proposal, and if we move forward with a more reference based spec these rules will become increasingly important. I will admit I'm not smart enough to fully understand the implications though, would it be possible for @Fannon or others to present at a SIG, or another meeting? |
@jmenning-solace : Yes, this would benefit much from some explaining. I'd be happy to do that. |
@Fannon next meeting is next week -> asyncapi/community#51 |
This pull request has been automatically marked as stale because it has not had recent activity 😴 It will be closed in 120 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. There can be many reasons why some specific pull request has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model. Let us figure out together how to push this pull request forward. Connect with us through one of many communication channels we established here. Thank you for your patience ❤️ |
@Fannon you have listed a bunch of options and ways to solve this, however, as a reader, it is hard to keep track of all the pros and cons and understand the ripple effect (through tooling, etc). I have a hard time figuring out what this PR is trying to fix, and I guess it comes down to which direction we should take it. Since you have the knowledge, my suggestion would be that you pick the direction you would like to see AsyncAPI adopt, regardless of breaking change or not. See it as a perfect world, which option would then be best suited? That way you can focus the PR on one suggestion that highlights the changes it requires, as well as letting others know why you chose it and why not one of the other options. You can also do it in multiple stages, so you start by I think this issue is definitely something that should be addressed, so thanks for taking the time! |
Hi @jonaslagoni, yes, I see that this PR is hard to understand in its current state. Only in the code-example I have a second option (not using JSON merge patch, but an own definition of merge algorithm + implementatoin). There is also one PR that only documents the status quo: #517 Best, |
So I've thought about this a bit more in another context. In this PR I've tried to show a compromise solution, chaning the order of inheritance but keeping the JSON Merge Patch behavior. My personal opinion on this has changed even more in the direction that we should not use JSON Merge Patch for defining the merge behavior:
To sum it up: My proposal would be to define our own merge algorithm (It's not that much anyway) in written form and additionally as a reference code example, inkcl. unit tests with example data. |
This pull request has been automatically marked as stale because it has not had recent activity 😴 It will be closed in 120 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. There can be many reasons why some specific pull request has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model. Let us figure out together how to push this pull request forward. Connect with us through one of many communication channels we established here. Thank you for your patience ❤️ |
Hello @fmvilas, |
I think we even already have a nice definition which was filed within #108:
We could extend this definition to:
|
Yeah, as long as the PR is open we still have time 😄 In any case, I'm not the champion of this issue but @Fannon is. |
@@ -139,6 +139,21 @@ This is applicable for `$ref` fields in the specification as follows from the [J | |||
|
|||
By convention, the AsyncAPI Specification (A2S) file is named `asyncapi.json` or `asyncapi.yaml`. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec should define "traits" before explaining their behavior. My suggestion from the PR conversation:
### <a name="traits"></a>Traits
Traits are pieces of information that will be merged into the referencing object. Using traits reduces the amount of repetitive code within an AsyncAPI document.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added this now to the PR just above the ### Trait Inheritance Section
as suggested by @patrickp-at-work
Kudos, SonarCloud Quality Gate passed! |
So how do we want to proceed with this? Right now, this PR / issue is in a complicated state, because to me it is not really clear which direction we want to take and how this would be decided. We've discussed a few options, here are the ones that I find most sensible / realistic.
I can also imagine that with the restructuring of AsyncAPI 3, a few circumstances have changed and new insights have been gained. Maybe that also changes our perspective here ;) |
8805c88
to
624ad52
Compare
This pull request has been automatically marked as stale because it has not had recent activity 😴 It will be closed in 120 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. There can be many reasons why some specific pull request has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model. Let us figure out together how to push this pull request forward. Connect with us through one of many communication channels we established here. Thank you for your patience ❤️ |
title: Redefine and explicitly formalize the trait inheritance behavior
Related issue(s): #505
Related PR(s): #517 (will be deprecated by this PR)
Code Example: https://jsfiddle.net/FannonF/yLsonr57/latest/
The basic issue is that the current defined trait merging behavior would overwrite the target object with the traits.
This might not what you would expect from trait inheritance and potentially limits the usefulness of traits, as they can't be used for inheritance use-cases.
There are three options that are proposed:
null
behaviorIn case we go for an option in the "B range", we have to decide:
For a detailed description and discussion of the problem, see #505 and its comments.
Related Material / Inspiration
Open Questions / Problems
null
values, which may not be useful / expected for trait inheritance